package com.sd365.gateway.core.filter;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.sd365.gateway.core.bo.UserBo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.util.Base64;
import java.util.List;


@Slf4j
@RefreshScope
@Component
public class BlackOrWhiteToken implements GlobalFilter, Ordered {

    @Autowired
    private RedisTemplate redisTemplate;
    @Value("${keypres}")
    private String KEY_PRES;
    private static final String MSG = "您已被列入黑名单,不可以登录！";
    /**
     * 设置系统运行模式 Normal 为正常 ，Degrade 为降级
     */

    @Value("${system.run.level}")
    private String systemRunLevel;
    /**
     * 系统降级常亮将在配置中心配置可以触发系统降级
     */
    private final static String RUN_LEVEL_NORMAL = "Normal";
    private final static String RUN_LEVEL_DEGRADE = "Degrade";

    /**
     * 白名单
     */
    private static final Byte WHITE = 1;
    /**
     * 黑名单
     */
    private static final Byte BLACKLIST = 2;
    /**
     * 普通用户
     */
    private static final Byte CONSUMER = 3;

    private Byte blackorWhiteToken(String token, String url) {


        token = token.split("\\.")[1];
        token = token.substring(0, token.length() - 1);
        String str = new String(Base64.getDecoder().decode(token.getBytes()));
        UserBo userBo = JSONObject.parseObject(str, UserBo.class);
        Object o = redisTemplate.opsForValue().get(KEY_PRES + userBo.getCode());
        if (ObjectUtils.isEmpty(o)) {
            return CONSUMER;
        } else {
            UserBo blacklist = JSON.parseObject(JSON.toJSONString(o), UserBo.class);
            if (!ObjectUtils.isEmpty(blacklist)) {
                if (blacklist.getType().equals("黑名单")) {
                    return BLACKLIST;
                } else {
                    return WHITE;
                }
            }
            return CONSUMER;
        }
    }

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        log.info("白名单过滤器1{}", this);
        String URI = exchange.getRequest().getURI().toString();
        Boolean flag = false;
        if (URI.contains("user/info") || URI.contains("user/logout")) {
            log.info("白名单过滤器2{}", "登录请求");
            return chain.filter(exchange);
        }
        List<String> accessToken = exchange.getRequest().getHeaders().get("accessToken");
        if (!CollectionUtils.isEmpty(accessToken)) {
            Byte userType = blackorWhiteToken(accessToken.toString(), null);
            /**
             * 系统正常运行 黑名单可以不可以过，白名单和正常用户可以
             */
            if (systemRunLevel.equalsIgnoreCase(RUN_LEVEL_NORMAL)) {
                if (userType.compareTo(BLACKLIST) == 0) {
                    log.info("白名单过滤器3{}", MSG);
                    return exchange.getResponse().writeWith(Flux.just(exchange.getResponse().bufferFactory().wrap(MSG.getBytes())));
                } else {
                    log.info("白名单过滤器4{}", "放行");
                    return chain.filter(exchange);
                }
            } else {
                if (userType.compareTo(WHITE) == 0) {
                    log.info("白名单过滤器5{}", "放行");
                    return chain.filter(exchange);
                } else {
                    log.info("白名单过滤器5{}", "放行");
                    return exchange.getResponse().writeWith(Flux.just(exchange.getResponse().bufferFactory().wrap(MSG.getBytes())));
                }
            }
        }
        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 10;
    }
}
